home *** CD-ROM | disk | FTP | other *** search
- /* Loading of .O files */
-
- #include "params.h"
- #include "gambit.h"
- #include "struct.h"
- #include "os.h"
- #include "mem.h"
- #include "strings.h"
- #include "opcodes.h"
- #include "run.h"
- #include "stats.h"
- #include "emul.h"
-
-
- /*---------------------------------------------------------------------------*/
-
-
- struct patch_rec {
- struct patch_rec *next; /* next entry in the patch list */
- long index; /* index to value's source */
- SCM_obj *loc; /* pointer to location to patch to */
- };
-
- typedef struct patch_rec *PATCH_PTR;
-
-
- char *alloc_ptr, *read_bot, *read_top, *load_bot, *load_top, *load_ptr;
- SCM_obj *object;
- PATCH_PTR free_patches, prim_patches;
- char *filename, *procedure_name;
-
-
- char *alloc( len )
- long len;
- { long len2 = ceiling8( len );
- if (alloc_ptr-len2 < read_top)
- { os_err = "Load memory overflow"; return NULL; }
- alloc_ptr -= len2;
- return alloc_ptr;
- }
-
-
- long begin_load()
- { free_patches = NULL;
- prim_patches = NULL;
- read_bot = pstate->heap_old;
- alloc_ptr = read_bot + (pstate->heap_mid - pstate->heap_bot);
- read_top = read_bot;
- object = (SCM_obj *)alloc( sizeof(SCM_obj) * (long)MAX_NB_OBJECTS_PER_FILE );
- return (object == NULL);
- }
-
-
- long end_load()
- { PATCH_PTR patch = prim_patches;
- while (patch != NULL)
- { SCM_obj val = sstate->globals[patch->index].value;
- if (val == (long)SCM_unbound)
- { os_err = string_append( "Undefined primitive, ",
- global_name(patch->index) );
- return 1;
- }
- *(patch->loc) += val; /* patch up reference to the primitive */
- patch = patch->next;
- }
- return 0;
- }
-
-
- long eof()
- { os_err = "Premature EOF";
- return 1;
- }
-
-
- #define load_long_word(var) \
- { if (load_ptr+4>load_top) return eof(); var = *(long *)load_ptr; load_ptr += 4; }
-
- #define load_word(var) \
- { if (load_ptr+2>load_top) return eof(); var = *(short *)load_ptr; load_ptr += 2; }
-
- #define load_words( n, ptr ) \
- { register long i = (n); register short *pt = (ptr); \
- if (load_ptr + i*2 > load_top) return eof(); \
- while (i>0) { *(pt++) = *(short *)load_ptr; load_ptr += 2; i--; } \
- }
-
-
- long load_string( str )
- char **str;
- { *str = load_ptr;
- while (*(load_ptr++) != '\0') if (load_ptr > load_top) return eof();
- load_ptr = (char *)ceiling2( load_ptr );
- if (load_ptr > load_top) return eof();
- return 0;
- }
-
-
- long skip_string( offset )
- long *offset;
- { *offset = load_ptr - load_bot;
- while (*(load_ptr++) != '\0') if (load_ptr > load_top) return eof();
- load_ptr = (char *)ceiling2( load_ptr );
- if (load_ptr > load_top) return eof();
- return 0;
- }
-
-
- /*---------------------------------------------------------------------------*/
-
-
- long nb_objects, highest_object, nb_symbols;
- PATCH_PTR object_patches, M68020_patches, M68881_patches;
-
-
- long add_object( value )
- SCM_obj value;
- { long i = nb_objects++;
- if (i + nb_symbols >= (long)MAX_NB_OBJECTS_PER_FILE)
- { os_err = "Too many objects in an object file"; return 1; }
- object[i] = value;
- return 0;
- }
-
-
- long add_patch( list, index, loc )
- PATCH_PTR *list;
- long index;
- SCM_obj *loc;
- { PATCH_PTR patch;
- if (free_patches != NULL)
- { patch = free_patches;
- free_patches = free_patches->next;
- }
- else
- { patch = (PATCH_PTR)alloc( (long)sizeof(struct patch_rec) );
- if (patch == NULL) return 1;
- }
- patch->next = *list;
- patch->index = index;
- patch->loc = loc;
- *list = patch;
- return 0;
- }
-
-
- long add_prim_patch( index, loc )
- long index;
- SCM_obj *loc;
- { return add_patch( &prim_patches, index, loc );
- }
-
-
- long add_object_patch( index, loc )
- long index;
- SCM_obj *loc;
- { if (index + nb_symbols >= (long)MAX_NB_OBJECTS_PER_FILE)
- { os_err = "Object reference too big"; return 1; }
- if (index > highest_object) highest_object = index;
- return add_patch( &object_patches, index, loc );
- }
-
-
- long patchup_M68020_emul_code()
- { PATCH_PTR patch = M68020_patches;
- while (patch != NULL)
- { PATCH_PTR next = patch->next;
- if (emul_M68020_instr( (short *)patch->loc )) return 1;
- patch->next = free_patches;
- free_patches = patch;
- patch = next;
- }
- return 0;
- }
-
-
- long patchup_M68881_emul_code()
- { PATCH_PTR patch = M68881_patches;
- while (patch != NULL)
- { PATCH_PTR next = patch->next;
- if (emul_M68881_instr( (short *)patch->loc )) return 1;
- patch->next = free_patches;
- free_patches = patch;
- patch = next;
- }
- return 0;
- }
-
-
- long load_sym( i, loc )
- short i;
- SCM_obj *loc;
- { if (i == INDEX_MASK)
- { char *name;
- long j = nb_symbols++;
- if (j + nb_objects >= (long)MAX_NB_OBJECTS_PER_FILE)
- { os_err = "Too many symbols in an object file"; return 1; }
- if (load_string( &name )) return 1;
- if (alloc_symbol( name, loc )) return 1;
- object[MAX_NB_OBJECTS_PER_FILE-1-j] = *loc;
- }
- else if (i > nb_symbols)
- { os_err = "Symbol reference out of range"; return 1; }
- else
- *loc = object[MAX_NB_OBJECTS_PER_FILE-1-i];
- return 0;
- }
-
-
- long load_value( loc )
- SCM_obj *loc;
- { long val, masked;
- load_long_word( val );
- masked = val & ~(((long)INDEX_MASK) << 3);
- if (masked == (long)OBJECT)
- { *loc = (SCM_obj)0;
- if (add_object_patch( (val >> 3) & INDEX_MASK, loc )) return 1;
- }
- else if (masked == (long)SYMBOL)
- { if (load_sym( (short)((val >> 3) & INDEX_MASK), loc )) return 1;
- }
- else if (masked == (long)PRIM_PROC)
- { SCM_obj sym;
- long index;
- if (load_sym( (short)((val >> 3) & INDEX_MASK), &sym )) return 1;
- if (alloc_global_from_symbol( sym, &index )) return 1;
- if (add_prim_patch( index, loc )) return 1;
- *loc = (SCM_obj)0;
- }
- else
- *loc = (SCM_obj)val;
- return 0;
- }
-
-
- long load_proc( proc_adr, len, name )
- SCM_obj proc_adr;
- long len;
- char *name;
- { short *code_ptr = (short *)proc_adr;
-
- procedure_name = name;
-
- M68020_patches = NULL;
- M68881_patches = NULL;
-
- while (1)
- { short tag;
-
- load_word( tag );
-
- if (tag > 0)
- { load_words( tag, code_ptr );
- code_ptr += tag;
- }
-
- else if (tag == (short)PADDING_TAG)
- /* just skip */;
-
- else if (tag == (short)END_OF_CODE_TAG)
- break;
-
- else if (tag == (short)M68020_TAG)
- { if (!os_M68020)
- if (add_patch( &M68020_patches, 0L, (SCM_obj *)code_ptr )) return 1;
- }
-
- else if (tag == (short)M68881_TAG)
- { if (!os_M68881)
- if (add_patch( &M68881_patches, 0L, (SCM_obj *)code_ptr )) return 1;
- }
-
- else if (tag == (short)STAT_TAG)
- { long index;
- if (alloc_stat( &index ))
- { os_err = "Statistics table overflow"; return 1; }
- else
- { *(long **)code_ptr = &pstate->stats_counters[index];
- code_ptr += 2;
- if (skip_string( &sstate->stats_offsets[index] )) return 1;
- }
- }
-
- else
- { short i = tag & INDEX_MASK;
- tag = tag & ~INDEX_MASK;
-
- if (tag == (short)PROC_REF_TAG)
- { if (add_object_patch( (long)i, (SCM_obj *)code_ptr )) return 1;
- load_word( *(long *)code_ptr );
- code_ptr += 2;
- }
-
- else if (tag == (short)GLOBAL_VAR_REF_TAG)
- { SCM_obj sym;
- long index;
- if (load_sym( i, &sym )) return 1;
- if (alloc_global_from_symbol( sym, &index )) return 1;
- *(code_ptr++) = table_offset( &sstate->globals[index].value );
- }
-
- else if (tag == (short)GLOBAL_VAR_SET_TAG)
- { SCM_obj sym;
- long index;
- if (load_sym( i, &sym )) return 1;
- if (alloc_global_from_symbol( sym, &index )) return 1;
- *(code_ptr++) = table_offset( &sstate->globals[index].value );
- *(code_ptr++) = LEAA6_DISP_A1_OP;
- *(code_ptr++) = table_offset( &sstate->tramps[index] );
- *(code_ptr++) = MOVE_L_A1_A6_DISP_OP;
- *(code_ptr++) = table_offset( &sstate->globals[index].jump_adr );
- }
-
- else if (tag == (short)GLOBAL_VAR_REF_JUMP_TAG)
- { SCM_obj sym;
- long index;
- if (load_sym( i, &sym )) return 1;
- if (alloc_global_from_symbol( sym, &index )) return 1;
- *(code_ptr++) = table_offset( &sstate->globals[index].jump_adr );
- }
-
- else if (tag == (short)PRIM_REF_TAG)
- { SCM_obj sym;
- long index;
- if (load_sym( i, &sym )) return 1;
- if (alloc_global_from_symbol( sym, &index )) return 1;
- if (add_prim_patch( index, (SCM_obj *)code_ptr )) return 1;
- load_word( *(long *)code_ptr );
- code_ptr += 2;
- }
-
- else
- { os_err = "Procedure object format error"; return 1; }
- }
-
- }
-
- { long i, rest = len - ( ((long)code_ptr) - ((long)proc_adr) - 2 );
- if ((rest < 0L) || ((rest & 3L) != 0))
- { os_err = "Procedure object format error"; return 1; }
- for (i=rest/4; i>0; i--)
- { if (load_value( (SCM_obj *)code_ptr )) return 1;
- code_ptr += 2;
- }
- }
-
- /* do patchup for emulation code */
-
- if (patchup_M68020_emul_code()) return 1;
-
- if (patchup_M68881_emul_code()) return 1;
-
- procedure_name = NULL;
- return 0;
- }
-
-
- long load_mem( index, ptr, len, init_proc )
- long index;
- char *ptr;
- long len;
- SCM_obj *init_proc;
- { short version_major, version_minor;
- char *emul_code_start = pstate->emul_code_ptr;
-
- emul_code_top = pstate->emul_code_top;
- emul_code_alloc = emul_code_start;
-
- load_bot = ptr;
- load_top = ptr+len;
- load_ptr = ptr;
-
- nb_objects = 0;
- nb_symbols = 0;
- highest_object = -1;
- object_patches = NULL;
- stats_begin( index );
-
- load_word( version_major );
- if (version_major < OFILE_VERSION_MAJOR)
- { os_err = "Old object file format"; return 1; }
- else if (version_major > OFILE_VERSION_MAJOR)
- { os_err = "New object file format"; return 1; }
- load_word( version_minor );
-
- while (load_ptr+4 <= load_top)
- { long prefix;
- load_long_word( prefix );
-
- switch (prefix)
- {
- case (long)PRIM_PROC_PREFIX:
- { SCM_obj adr, sym;
- long indx, l;
- short header, i;
- char *name;
- load_word( i );
- if (load_sym( i, &sym )) return 1;
- if (alloc_global_from_symbol( sym, &indx )) return 1;
- name = SCM_obj_to_str(SCM_obj_to_vect(sym)[SYMBOL_NAME]);
- load_word( header );
- if (header >= 0)
- { os_err = "Object file format error"; return 1; }
- l = header + 0x8000;
- if (sstate->debug>=2)
- { os_warn( " (primitive procedure %s", (long)name );
- os_warn( ", length=%d)\n", l );
- }
- if (alloc_const_proc( l, &adr )) return 1;
- if (add_object( adr )) return 1;
- if (load_proc( adr, l, name )) return 1;
- if ((sstate->debug>=2) &&
- (sstate->globals[indx].value != (long)SCM_unbound))
- os_warn( "Redefining %s\n", (long)name );
- sstate->globals[indx].value = adr;
- sstate->globals[indx].jump_adr = (long)&sstate->tramps[indx];
- break;
- }
-
- case (long)USER_PROC_PREFIX:
- { SCM_obj adr;
- long l;
- short header;
- load_word( header );
- if (header >= 0)
- { os_err = "Object file format error"; return 1; }
- l = header + 0x8000;
- if (sstate->debug>=2) os_warn( " (procedure, length=%d)\n", l );
- if (alloc_const_proc( l, &adr )) return 1;
- if (add_object( adr )) return 1;
- if (load_proc( adr, l, (char *)NULL )) return 1;
- break;
- }
-
- case (long)PAIR_PREFIX:
- { SCM_obj pair_adr;
- if (sstate->debug>=2) os_warn( " (pair)\n", 0L );
- if (alloc_const_pair( &pair_adr )) return 1;
- if (add_object( pair_adr )) return 1;
- if (load_value( (SCM_obj *)(pair_adr-SCM_type_PAIR+PAIR_CDR*sizeof(SCM_obj)) )) return 1;
- if (load_value( (SCM_obj *)(pair_adr-SCM_type_PAIR+PAIR_CAR*sizeof(SCM_obj)) )) return 1;
- break;
- }
-
- default:
- { SCM_obj vector_adr;
- long l = SCM_header_length( prefix );
- long subtype = SCM_header_subtype( prefix );
- if (alloc_const_subtyped( l, subtype, &vector_adr )) return 1;
- if (add_object( vector_adr )) return 1;
-
- if (SCM_subtype_is_ovector( subtype ))
- { long i, n = l/4;
- if (sstate->debug>=2)
- os_warn( " (object vector; length=%d)\n", n );
- for (i=0; i<n; i++)
- if (load_value( &SCM_obj_to_vect(vector_adr)[i] )) return 1;
- }
-
- else
-
- { short *p = (short *)SCM_obj_to_vect(vector_adr);
- if (sstate->debug>=2)
- os_warn( " (byte vector; length=%d)\n", l );
- load_words( (l + 1)/2, p );
- }
-
- break;
- }
- }
- }
-
- if (nb_objects < 1) { os_err = "Object file is empty"; return 1; }
-
- stats_end( index );
-
- /* do patchup for local object references */
-
- if (highest_object >= nb_objects)
- { os_err = "Unresolved local object reference(s)"; return 1; }
-
- { PATCH_PTR patch = object_patches;
- while (patch != NULL)
- { PATCH_PTR next = patch->next;
- *(patch->loc) += object[patch->index];
- patch->next = free_patches;
- free_patches = patch;
- patch = next;
- }
- }
-
- /* copy emulation code to all other processors */
-
- { long i;
- long l = emul_code_alloc - emul_code_start;
- for (i=SCM_obj_to_int(pstate->nb_processors)-1; i>=0; i--)
- { PSTATE_PTR p = pstate->ps[i];
- if (p != pstate)
- os_block_copy( emul_code_start, p->emul_code_ptr, l );
- p->emul_code_ptr += l;
- }
- }
-
- *init_proc = object[0];
-
- return 0;
- }
-
-
- long load_file( index, init_proc )
- long index;
- SCM_obj *init_proc;
- { OS_FILE input;
- long len;
-
- filename = string_append( sstate->ofile[index].ptr, ".O" );
- if (filename == NULL) { os_err = NULL; return 1; }
- input = os_file_open_input( filename );
- if (input == -1L) { os_err = "Can't open"; return 1; }
- len = os_file_length( input );
- if (len < 0L) { os_err = "Read error"; return 1; }
- if (sstate->debug>=1)
- { os_warn( "Loading %s", (long)filename );
- os_warn( " (length=%d)\n", len );
- }
-
- read_top = read_bot+len;
- if (read_top > alloc_ptr)
- { os_file_close( input ); os_err = "Load memory overflow"; return 1; }
-
- if (os_file_read( input, read_bot, len ) != len)
- { os_file_close( input ); os_err = "Read error"; return 1; }
-
- os_file_close( input );
-
- if (load_mem( index, read_bot, len, init_proc )) return 1;
-
- filename = NULL;
- return 0;
- }
-
-
- void fill_in_os_err()
- { char *fn, *pn, *em;
- if (filename == NULL) fn = ""; else fn = string_append( filename, ": " );
- if (procedure_name == NULL) pn = ""; else pn = string_append( procedure_name, ", " );
- if (os_err == NULL) em = "Local memory overflow"; else em = os_err;
- os_err = string_append( fn, string_append( pn, em ) );
- if (os_err == NULL) os_err = "Local memory overflow";
- }
-
-
- long prepare_ofile( ptr, len )
- char *ptr;
- long len;
- { long i;
- if (len == 0)
- { for (i=0; i<sstate->nb_ofiles; i++)
- if ((sstate->ofile[i].len == 0) &&
- (string_compare( sstate->ofile[i].ptr, ptr ) == 0)) break;
- }
- else
- i = sstate->nb_ofiles;
-
- if (i >= (long)MAX_NB_OFILES)
- { os_err = "Too many object files"; return -1; }
-
- sstate->ofile[i].ptr = ptr;
- sstate->ofile[i].len = len;
- stats_clear( i );
- if (i == sstate->nb_ofiles) sstate->nb_ofiles++;
- return i;
- }
-
-
- void init_ofile( ptr, len )
- char *ptr;
- long len;
- { if (prepare_ofile( ptr, len ) < 0)
- { os_warn( "%s\n", (long)os_err ); os_quit(); }
- }
-
-
- SCM_obj init_program( argc, argv, envp )
- long argc;
- char *argv[], *envp[];
- { long i;
- long envc;
- SCM_obj ev, av, ep;
-
- filename = NULL;
- procedure_name = NULL;
-
- if (alloc_const_vector( sstate->nb_ofiles, &ev )) goto error;
-
- if (begin_load()) goto error;
-
- for (i=0; i<sstate->nb_ofiles; i++)
- if (sstate->ofile[i].len == 0)
- { if (load_file( i, &SCM_obj_to_vect(ev)[i] )) goto error; }
- else
- { if (load_mem( i,
- sstate->ofile[i].ptr,
- sstate->ofile[i].len,
- &SCM_obj_to_vect(ev)[i] )) goto error;
- }
-
- if (end_load()) goto error;
-
- /* init trap trampolines */
-
- for (i=0; i<NB_TRAMPOLINE_TRAPS; i++)
- { long index;
- static char prefix[] = "###_kernel.trap_";
- char name[sizeof(prefix)+2], *p1 = name, *p2 = prefix;
- while (*p2 != '\0') *p1++ = *p2++;
- if (i > 9) *p1++ = '0' + (i/10);
- *p1++ = '0' + (i%10);
- *p1++ = '\0';
- if (alloc_global( name, &index )) goto error;
- sstate->traps[i].jmp = JMP_OP;
- sstate->traps[i].adr = sstate->globals[index].value;
- }
-
- /* init interrupt trap */
-
- { long index;
- if (alloc_global( "###_kernel.interrupt", &index )) goto error;
- sstate->traps[intr_trap].jmp = JMP_OP;
- sstate->traps[intr_trap].adr = sstate->globals[index].value;
- }
-
- if (set_global( "##exec-vector", ev )) goto error;
-
- if (set_global( "##argc", SCM_int_to_obj(argc) )) goto error;
-
- if (alloc_const_vector( argc, &av )) goto error;
- for (i=0; i<argc; i++)
- if (alloc_const_string( argv[i], &SCM_obj_to_vect(av)[i] )) goto error;
- if (set_global( "##argv", av )) goto error;
-
- envc = 0;
- while (envp[envc] != NULL) envc++;
- if (alloc_const_vector( envc, &ep )) goto error;
- for (i=0; i<envc; i++)
- if (alloc_const_string( envp[i], &SCM_obj_to_vect(ep)[i] )) goto error;
- if (set_global( "##envp", ep )) goto error;
-
- return SCM_obj_to_vect(ev)[0];
-
- error:
- fill_in_os_err();
- os_warn( "%s\n", (long)os_err );
- os_quit();
- /*NOTREACHED*/
- }
-
-
- long do_load_copy_code( id, ptr )
- long id;
- char *ptr;
- { if (id != SCM_obj_to_int(pstate->id))
- { long len1 = ((long *)ptr)[0];
- long len2 = ((long *)ptr)[1];
- os_block_copy( ptr+2*sizeof(long), sstate->const_bptr - len1 , len1 );
- os_block_copy( ptr+2*sizeof(long)+len1, sstate->const_tptr, len2 );
- }
- return 0;
- }
-
-
- long load_ofile( name, init_proc )
- char *name;
- SCM_obj *init_proc;
- { if (name != NULL) /* only one processor does the load */
- { long index;
- char *const_b = sstate->const_bptr;
- char *const_t = sstate->const_tptr;
-
- os_err = "";
-
- filename = NULL;
- procedure_name = NULL;
-
- index = prepare_ofile( name, 0L );
- if (index < 0) goto error;
-
- if (begin_load()) goto error;
-
- if (load_file( index, init_proc )) goto error;
-
- if (end_load()) goto error;
-
- /* copy code to each processor */
-
- { long len1 = sstate->const_bptr - const_b;
- long len2 = const_t - sstate->const_tptr;
- if (len1+len2+2*sizeof(long) > pstate->heap_mid - pstate->heap_bot)
- goto error;
- ((long *)pstate->heap_old)[0] = len1;
- ((long *)pstate->heap_old)[1] = len2;
- os_block_copy( const_b, pstate->heap_old+2*sizeof(long), len1 );
- os_block_copy( sstate->const_tptr, pstate->heap_old+2*sizeof(long)+len1, len2 );
- return barrier_call( do_load_copy_code, (long)pstate->heap_old );
- }
-
- error:
- fill_in_os_err();
- if (sstate->debug>=1) os_warn( "%s\n", (long)os_err );
- *init_proc = c_str_to_string( os_err );
- return barrier_call( do_return, 1L );
- }
- else
- return barrier_service();
- }
-
-
- /*---------------------------------------------------------------------------*/
-